package com.yc.project3_bestMatching;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 线程池的任务分配及调度，结果汇总
 */
public class BestMatchingConcurrentCalculation {
    /**
     *  线程池的任务分配及调度，结果汇总
     * @param word
     * @param dictionary
     * @return
     */
    public static BestMatchingData getBestMatchingWords( String word, List<String> dictionary ) throws InterruptedException, ExecutionException {
        BestMatchingData result = new BestMatchingData();
        //1.任务数
        int numCores =Runtime.getRuntime().availableProcessors();//单例的
        ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(numCores);
        //2.计算每个任务对应的词汇量 startIndex  endIndex
        int size= dictionary.size();
        int step= size/numCores;  //任务的分区大小
        int startIndex,endIndex;
        //将所有的任务存在一个集合中
        List<BestMatchingTask> tasks =new ArrayList<>();
        //3.创建 BestMatchingTask
        for (int i=0;i<numCores;i++) {
            startIndex =i*step;
            //endIndex
            if (i== numCores-1) {
                endIndex =size;
            }else{
                endIndex = (i+1)*step;
            }
            BestMatchingTask task = new BestMatchingTask(dictionary, word, startIndex, endIndex);
            tasks.add( task);
        }
        //4.将上面创建的BestMatchingTask提交给 Executor线程池执行器运行，
        //invokeAll一次性提交任务后， 只有所有的任务全部执行完毕，才会向下运行 即程序会阻塞此处
        List<Future<BestMatchingData>> listFuture = executor.invokeAll(tasks);//激活所有 一次性提交所有的任务  上一个任务 一次只提交一个任务
        System.out.println("如果任务没有完成， invokeAll 阻塞此处");
        executor.shutdown();//  因为任务完成了，所以关闭执行器
        //5.通过FutureTask. get()获取以上任务的执行结果BestMatchingData, 汇总( 找最小距离及对应的词汇表
        int minDistance =Integer.MAX_VALUE;
        List<String> words = new ArrayList<>(); //最短距离对应的单词
        for (Future<BestMatchingData> future:listFuture) {
            BestMatchingData bestMatchingData =future.get();
            if (bestMatchingData.getDistance() < minDistance) {
                words.clear(); //清空原有的
                minDistance= bestMatchingData.getDistance(); ////记录新的最短距离
                words.addAll(bestMatchingData.getWords());
            } else if (bestMatchingData.getDistance() == minDistance) {
                //这个任务找刭最短距离与已知的一样,则合并单词列表
                words.addAll(bestMatchingData.getWords());
            }
        }
        //6. 包装成BestMatchingData
        result.setDistance(minDistance);
        result.setWords(words);
        return result;
    }

}
